<?php
/*
 * $Id: IndexSearcherTest.class.php 149 2009-12-16 15:55:50Z namba0219 $
 * =============================================================================
 * Barge - web application framework on PHP5
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * =============================================================================
 * For more information, see http://barge.googlecode.com/
 */
namespace barge\lucene;

use \UnitTestCase;

use barge\logging\LogFactory;

use barge\lucene\Document;
use barge\lucene\Field;
use barge\lucene\IndexReader;
use barge\lucene\IndexSearcher;
use barge\lucene\IndexWriter;
use barge\lucene\MultiTermQuery;
use barge\lucene\BooleanQuery;
use barge\lucene\TermQuery;
use barge\lucene\StandardAnalyzer;
use barge\lucene\Term;



/**
 * @see UnitTestCase
 */
class IndexSearcherTest extends UnitTestCase
{
	/**
	 * @return string
	 */
	private $indexDir;

	/**
	 * @test
	 */
	public function setUp()
	{
		$this->indexDir = dirname(__FILE__).'/index';
		@mkdir($this->indexDir);
	}

	/**
	 * @test
	 */
	public function testSearch1()
	{
		$analyzer = new StandardAnalyzer();

		$indexWriter = new IndexWriter($this->indexDir, $analyzer);
		$doc = new Document();
		$doc->addField(new Field('name', 'Google', true, false));
		$doc->addField(new Field('description', 'Google is high performance search engine.', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('name', 'Yahoo', true, false));
		$doc->addField(new Field('description', 'Yahoo is famous for potal site.', true, true));
		$indexWriter->addDocument($doc);
		$indexWriter->commit();
		$indexWriter->close();


		$searcher = new IndexSearcher($this->indexDir, $analyzer);
		$query = new TermQuery(new Term('name', 'Yahoo'));
		$hits = $searcher->search($query);
//var_dump($hits);
		$this->assertIdentical($hits->size(), 1);
		$doc = $hits[0]->getDocument();
		$this->assertIdentical($doc->getFieldValue('name'), 'Yahoo');
	}

	/**
	 * BooleanQuery
	 *
	 * @test
	 */
	public function testSearch2()
	{
		$analyzer = new StandardAnalyzer();

		// Create index.
		$this->indexPHPFunctins($this->indexDir, $analyzer);

		$searcher = new IndexSearcher($this->indexDir, $analyzer);
		$query = new TermQuery(new Term('category', 'string'));
		$hits = $searcher->search($query);
//LogFactory::getLogger()->debug("AAAAAAAAAAAA");
		$this->assertIdentical(2, $hits->size());
		$query = new BooleanQuery('description');
		$query->addQuery(new TermQuery(new Term('category', 'string')), BooleanQuery::SHOULD);
		$query->addQuery(new TermQuery(new Term('function', 'strstr')), BooleanQuery::SHOULD);
		$hits = $searcher->search($query);
//var_dump($hits);
		$this->assertIdentical(2, $hits->size());

		$query = new BooleanQuery('description');
		$query->addQuery(new TermQuery(new Term('category', 'string')), BooleanQuery::MUST);
		$query->addQuery(new TermQuery(new Term('function', 'strstr')), BooleanQuery::MUST);
		$hits = $searcher->search($query);
		$this->assertIdentical(1, $hits->size());

		$searcher->close();
	}


	/**
	 * ソート
	 * @test
	 */
	public function testSearch3()
	{
		$analyzer = new StandardAnalyzer();

		// Create index.
		$this->indexPHPFunctins($this->indexDir, $analyzer);

		$searcher = new IndexSearcher($this->indexDir, $analyzer);
		$query = new TermQuery(new Term('category', 'array'));
		$sort = new FieldSort();
		$sort->addField('id');
		$hits = $searcher->search($query, $sort);
		$this->assertIdentical($hits->size(), 2);
		$this->assertIdentical($hits[0]->getDocument()->getFieldValue('id'), "1");
		$this->assertIdentical($hits[1]->getDocument()->getFieldValue('id'), "2");

		$sort = new FieldSort();
		$sort->addField('id', true);
		$hits = $searcher->search($query, $sort);
		$this->assertTrue(count($hits) === 2);
		$this->assertIdentical($hits[0]->getDocument()->getFieldValue('id'), "2");
		$this->assertIdentical($hits[1]->getDocument()->getFieldValue('id'), "1");

		$searcher->close();
	}

	/**
	 * ウェイト
	 * @test
	 */
	public function testSearch4()
	{
		$log = LogFactory::getLogger();
		$log->debug('<testSearch4>');

		$analyzer = new StandardAnalyzer();

		// Create index.
		$this->indexPHPFunctins($this->indexDir, $analyzer);

		$searcher = new IndexSearcher($this->indexDir, $analyzer);

		$query = new BooleanQuery('description');
		$query->addQuery(new TermQuery(new Term('category', 'string')), BooleanQuery::SHOULD);
		$query->addQuery(new TermQuery(new Term('function', 'split')), BooleanQuery::SHOULD);
		$hits = $searcher->search($query, new ScoreSort());


//TODO :
$this->assertTrue(count($hits) > 1);

//		$this->assertIdentical($hits->size(), 2);
//		$this->assertIdentical($searcher->getDocument($hits[0]->getId())->getFieldValue('id'), "1");
//		$this->assertIdentical($searcher->getDocument($hits[1]->getId())->getFieldValue('id'), "2");
		$searcher->close();
	}

	/**
	 * スコアリング
	 * @test
	 */
	public function testSearch5()
	{
		$log = LogFactory::getLogger();

//throw new \Exception('aaa');
		$analyzer = new StandardAnalyzer();
		$indexWriter = new IndexWriter($this->indexDir, $analyzer);
		$doc = new Document();
		$doc->addField(new Field('id', '1', false, false));
		$doc->addField(new Field('text', '田町|の|居酒屋|へ|行く', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '2', false, false));
		$doc->addField(new Field('text', '品川|の|居酒屋|へ|行く', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '3', false, false));
		$doc->addField(new Field('text', '田町|の|レストラン|へ|行く', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '4', false, false));
		$doc->addField(new Field('text', '田町|の|居酒屋|と|レストラン|へ|行く', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '5', false, false));
		$doc->addField(new Field('text', '帰り|に|田町|の|居酒屋|へ|行く', true, true));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '6', false, false));
		$doc->addField(new Field('text', '田町|には|田町|の|良さ|が|ある', true, true));
		$indexWriter->addDocument($doc);
		$indexWriter->commit();
		$indexWriter->close();

		$searcher = new IndexSearcher($this->indexDir, $analyzer);
		$hits = $searcher->search(new TermQuery(new Term('text', '田町')), new ScoreSort());

		$this->assertIdentical(5, count($hits));
		$this->assertIdentical('6', $hits->get(0)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('1', $hits->get(1)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('3', $hits->get(2)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('4', $hits->get(3)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('5', $hits->get(4)->getDocument()->getFieldValue('id'));

		foreach ($hits as $i => $hit) {	/* @var $hit Hit */
			$doc = $hit->getDocument();
			$log->debug($doc->getFieldValue('id').':'.$doc->getFieldValue('text'));
			$log->debug(' score:'.$hit->getScore());
		}

		$searcher->close();
	}

	/**
	 * {@link MatchAllDocsQuery}
	 * @test
	 */
	public function testMatchAllDocsQuery()
	{
		$log = LogFactory::getLogger();

		$analyzer = new StandardAnalyzer();

		// Create index.
		$this->indexPHPFunctins($this->indexDir, $analyzer);

		$searcher = new IndexSearcher($this->indexDir, $analyzer);
		$query = new MatchAllDocsQuery();
		$hits = $searcher->search($query);

		$this->assertIdentical(4, $hits->size());
		$this->assertIdentical('1', $hits->get(0)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('2', $hits->get(1)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('3', $hits->get(2)->getDocument()->getFieldValue('id'));
		$this->assertIdentical('4', $hits->get(3)->getDocument()->getFieldValue('id'));

		$searcher->close();
	}

	/**
	 * @param string $dir
	 * @param $analyzer
	 */
	private function indexPHPFunctins($dir, $analyzer)
	{
		$indexWriter = new IndexWriter($dir, $analyzer);
		$doc = new Document();
		$doc->addField(new Field('id', '1', false, false));
		$doc->addField(new Field('function', 'sort', true, false));
		$doc->addField(new Field('description', 'Sort an array', true, true));
		$doc->addField(new Field('category', 'array', true, false));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '2', false, false));
		$doc->addField(new Field('function', 'array_chunk', true, false));
		$doc->addField(new Field('description', 'Split an array into chunks', true, true));
		$doc->addField(new Field('category', 'array', true, false));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '3', false, false));
		$doc->addField(new Field('function', 'split', true, false));
		$doc->addField(new Field('description', 'Split string into array by regular expression', true, true));
		$doc->addField(new Field('category', 'string', true, false));
		$indexWriter->addDocument($doc);
		$doc = new Document();
		$doc->addField(new Field('id', '4', false, false));
		$doc->addField(new Field('function', 'strstr', true, false));
		$doc->addField(new Field('description', 'Find first occurrence of a string', true, true));
		$doc->addField(new Field('category', 'string', true, false));
		$indexWriter->addDocument($doc);
		$indexWriter->commit();
		$indexWriter->close();
	}

}


?>